package com.ycxh.util;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.LinkedList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * zip工具类
 */
@Slf4j
public class ZipUtil {

    /**
     * 解压
     * https://blog.csdn.net/qq_37361360/article/details/117597742
     * @param fileIn 压缩文件输入流
     * @param dir    解压目录
     */
    public boolean unzipByInputStream(InputStream fileIn, String dir) {
        boolean rs = false;
        if (fileIn == null || dir == null) {
            return rs;
        }
        // 先备份原目录，即改名
        File destFile = new File(dir);
        if (destFile.exists() && destFile.isDirectory()) {
            // 存在则改名
            String targetFileName = destFile.getName();
            // 备份文件名
            String bakFileName = targetFileName + "_bak" + System.currentTimeMillis();
            File bakFile = new File(destFile.getParentFile() + File.separator + bakFileName);
            if (destFile.renameTo(bakFile)) {
                log.info("重命名成功");
            } else {
                log.error("重命名失败");
                return rs;
            }
        } else {
            log.info("解压目录不存在");
            return rs;
        }

        ZipInputStream zipIn = null;
        try {
            zipIn = new ZipInputStream(fileIn);
            ZipEntry each = zipIn.getNextEntry();
            byte[] buffer = new byte[10240];
            while (each != null) {
                // 222/1345_banner-3.png  111.txt
                // build/static/ 可能是文件夹
                // build/static/css/
                // 还原，旧文件夹也不一定有
                System.out.println(each.getName());
                String out = FileUtil.getFilePath(dir, each.getName());
                File eachFile = new File(out);
                if (each.isDirectory()) {
                    // 如果是文件夹
                    eachFile.mkdirs();
                    each = zipIn.getNextEntry();
                    continue;
                }

                File pDir = eachFile.getParentFile();
                if (!pDir.exists()) {
                    pDir.mkdirs();
                }
                FileOutputStream output = null;
                try {
                    output = new FileOutputStream(out);
                    int len = 0;
                    while ((len = zipIn.read(buffer)) > 0) {
                        output.write(buffer, 0, len);
                    }
                } finally {
                    if (output != null) {
                        try {
                            output.close();
                        } catch (IOException e) {

                        }
                    }
                }
                each = zipIn.getNextEntry();
            }
            rs = true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (zipIn != null) {
                try {
                    zipIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileIn != null) {
                try {
                    fileIn.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        File[] files = destFile.listFiles();
        if (files != null && files.length == 1 && files[0].isDirectory()) {
            // 移动到上一级
            moveFileToParent(files[0]);
        }
        return rs;
    }

    // 移动当前文件夹下所有文件到父级(上一级)，空目录可以丢弃
    private static void moveFileToParent(File file) {
        // 栈(Stack) 后进先出
        String currentFile = file.getAbsolutePath();
        String parentFile = file.getParentFile().getAbsolutePath();
        System.out.println("currentFile = " + currentFile);
        System.out.println("parentFile = " + parentFile);
        LinkedList<File> list = new LinkedList<>();

        list.push(file);
        while (!list.isEmpty()) {
            File f = list.pop();
            System.out.println(f);
            if (f != null && f.isDirectory()) {
                // 文件调用返回null 空文件夹返回length=0 没有权限访问的文件夹返回null
                File[] files = f.listFiles();
                if (files != null) {
                    for (File fil : files) {
                        list.push(fil);
                    }
                }
            } else {
                // 移动到上一级，使用重命名
                // 绝对路径
                String absolutePath = f.getAbsolutePath();
                String newFilePath = absolutePath.replace(currentFile, parentFile);
                System.out.println("renameTo：" + f + "," + newFilePath);
                // 不同文件系统无法重命名 https://wenku.baidu.com/view/76826e09ac45b307e87101f69e3143323868f543.html
                // 重命名后的目录不存在，重命名失败，返回false https://blog.csdn.net/chenlang02/article/details/120646465
                File newFile = new File(newFilePath);
                // 目录不存在先创建
                File pDir = newFile.getParentFile();
                if (!pDir.exists()) {
                    pDir.mkdirs();
                }
                f.renameTo(newFile);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ZipUtil util = new ZipUtil();
        // File src = new File("D:\\Users\\333.zip");
        File src = new File("D:\\新建文件夹 (2)\\经营线表模板.zip");
        String dest = "D:\\新建文件夹 (2)\\testunzip";

        // 先备份原目录，即改名
        File destFile = new File(dest);
        if (!destFile.exists()) {
            destFile.mkdirs();
        }
        util.unzipByInputStream(new FileInputStream(src), dest);
        // moveFileToParent(new File(dest));
    }
}
